組件實作 : Demo
slideshow 幻燈片組件可以為網頁帶來動態的效果,與使用者產生互動,我們用 6 張圖片組成一個輪播視窗。你除了可以使用視窗兩側的箭頭來切換圖片,也可以按下小圓點來切換,slideshow 除了可放在<head>
當作顯眼的看板,也可以放在側邊欄或是文章內部等任何你想放置的地方,用途很廣泛。不說廢話,現在就開始來實作吧~
我們參考 How TO - Slideshow【1】來製作,首先,在一個 class 名稱為slide__item
的 div 中先加入文字和圖片等相關資訊,slide__item
總共需要製作 6 個,最外層我們用一個 class 名稱為slideshow
的 div 包住所有元素。
HTML:
<div class="slide__item fades">
<div class="slide__pagenumber">1 / 6</div>
<img src="https://picsum.photos/1920/400?random=1" />
<div class="slide__content">Hello page 1</div>
</div>
顯示結果:
快速介紹上述程式碼用途:slide__item
用來放一張幻燈片需要的所有元素,fades
是切換時的動畫效果,slide__pagenumber
放的是切換時顯示的頁數,img
則是使用 Fake images,slide__content
則是圖片的說明文字。
把剛剛的程式碼放到名稱為slideshow
的 div 中,看你要放多少張圖片,就寫多少個slide__item
。
HTML:
<div class="slideshow">
<div class="slide__item fades">
<div class="slide__pagenumber">1 / 6</div>
<img src="https://source.unsplash.com/random/1920x400?sig=1" />
<div class="slide__content">Hello page 1</div>
</div>
<div class="slide__item fades">
<div class="slide__pagenumber">2 / 6</div>
<img src="https://source.unsplash.com/random/1920x400?sig=2" />
<div class="slide__content">Hello page 2</div>
</div>
<div class="slide__item fades">
<div class="slide__pagenumber">3 / 6</div>
<img src="https://source.unsplash.com/random/1920x400?sig=3" />
<div class="slide__content">Hello page 3</div>
</div>
<div class="slide__item fades">
<div class="slide__pagenumber">4 / 6</div>
<img src="https://source.unsplash.com/random/1920x400?sig=4" />
<div class="slide__content">Hello page 4</div>
</div>
<div class="slide__item fades">
<div class="slide__pagenumber">5 / 6</div>
<img src="https://source.unsplash.com/random/1920x400?sig=5" />
<div class="slide__content">Hello page 5</div>
</div>
<div class="slide__item fades">
<div class="slide__pagenumber">6 / 6</div>
<img src="https://source.unsplash.com/random/1920x400?sig=6" />
<div class="slide__content">Hello page 6</div>
</div>
</div>
顯示結果:
左右兩側切換的箭頭按鈕,使用兩個 a 標籤來實作。
HTML:
<a id="prev" class="slide__arraw slide__arraw--prev"> ❮ </a>
<a id="next" class="slide__arraw slide__arraw--next"> ❯ </a>
製作六個小圓點,使用 class 名稱為dot
的 div 來製作。(data-value
只是用來識別有幾個dot
)。
HTML:
<div class="slide__dot">
<div class="dot" data-value="1"></div>
<div class="dot" data-value="2"></div>
<div class="dot" data-value="3"></div>
<div class="dot" data-value="4"></div>
<div class="dot" data-value="5"></div>
<div class="dot" data-value="6"></div>
</div>
小圓點的 CSS 的外觀製作,相關的屬性寫在 class 名稱為 dot 的 div 中。
CSS:
.dot {
width: 15px;
height: 15px;
margin: 0 5px;
border-radius: 50%;
border: 1px solid rgba(255, 255, 255, 0.1);
background: rgba(255, 255, 255, 0.3);
box-shadow: 0px 0px 2px 2px rgba(255, 255, 255, 0.3);
}
再來,為了讓畫面滿版,需要讓多餘 margin 和 padding 消失。
CSS:
* {
margin: 0;
padding: 0;
}
針對圖片的處理,我們想要一個寬度滿版,高度為 400 px 的圖片,object-fit
可以用來調整圖片的內容【1】。transition
用於動畫的過渡效果,例如 transition: 0.5s;
指的是整個動作要再 0.5 秒之內結束。而transform
有讓元素有各種效果【2】,比如讓圖片位移、旋轉、縮放等等,transform
可以搭配transition
使用,對於 img 相關的 CSS 設定如下。
CSS
img {
width: 100%;
height: 400px;
object-fit: cover;
vertical-align: middle;
transition: 0.5s;
}
img:hover {
transform: scale(1.5);
transition: 0.5s;
}
寫到這裡,你的圖片應該會有縮放的效果,在來是對slideshow
內部元素做設定,slideshow
是包在最外面的父層,我們用它來所有的圖片,以及剛剛的切換頁面箭頭和圓點位做修改。
CSS:
.slideshow {
position: relative;
transition: 2s;
user-select: none;
}
.slide__item {
display: none;
position: relative;
overflow: hidden;
}
.slide__pagenumber {
padding: 10px;
border-radius: 80% 30% / 80% 50%;
background: rgba(0, 0, 0, 0.7);
color: white;
position: absolute;
right: 0;
z-index: 1;
}
.slide__content {
position: absolute;
color: white;
background: rgba(0, 0, 0, 0.5);
bottom: 0;
padding: 0 10px;
border-radius: 5px;
}
.slide__arraw {
padding: 20px;
position: absolute;
line-height: 20px;
font-size: 20px;
text-decoration: none;
color: white;
}
.slide__arraw:hover {
background: rgba(0, 0, 0, 0.7);
border-radius: 5px;
color: white;
cursor: pointer;
transition: 0.6 ease;
}
.slide__arraw--prev {
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
}
.slide__arraw--next {
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
}
.slide__dot {
padding: 5px 5px;
display: flex;
position: absolute;
bottom: 0px;
left: 50%;
transform: translateX(-50%);
}
transform: translateX(-50%);
置中寫法可參考 position 用法【3】。
實際上,圖片的切換靠的是索引值slideIndex
(我們先預設slideIndex
值為1)的切換來決定要顯示哪一張圖片,主要的切換功能寫在 showSlide()
這個 Funciotn 中。那麼該如何更改slideIndex
的索引值呢?先直接看所有的 JavaScript 程式碼。
JavaScript:
window.onload = function () {
let slideIndex = 1;
showSlide(slideIndex);
let prev = document.getElementById("prev");
prev.addEventListener("click", divideSlides, false);
let next = document.getElementById("next");
next.addEventListener("click", plusSlides, false);
const selectdot = document.querySelectorAll(".dot");
for (let i = 0; i < selectdot.length; i++) {
selectdot[i].addEventListener("click", function (e) {
showSlide((slideIndex = i + 1));
});
}
function plusSlides() {
showSlide((slideIndex += 1));
}
function divideSlides() {
showSlide((slideIndex -= 1));
}
function showSlide(num) {
let slides = document.getElementsByClassName("slide__item");
let dots = document.getElementsByClassName("dot");
if (num > slides.length) {
slideIndex = 1;
}
if (num < 1) {
slideIndex = slides.length;
}
for (let i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
for (let i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace("active", "");
}
slides[slideIndex - 1].style.display = "block";
dots[slideIndex - 1].className += " active";
}
};
首先,slideIndex
的值設為 1,我們使用 prev 和 next 來當作 a 元素被切換時要做的事件監聽,prev
為左邊箭頭被按下時,會執行 divideSlides()
這個 Funciotn,就是把當前索引值 slideIndex 給減一
,而next
則是與prev
功能相似(使用plusSlides()
),只不過它是將索引值加一。
selectdot
則是處理那六個小圓點,每當小圓點被選擇時,slideIndex 索引值
會被改變,再來看showSlide
這個 Funciotn,slides
會對應到 class 名稱為slide__item
的 div,這東西其實是控制整個圖片,如果我們要讓圖片隱藏或是顯示,只要控制它就行。dots
則是用控制所有的 dot
,也就是所有的小圓點。
if (num < 1)
或是if (num < 1)
這個主要是判別索引值的大小,不要超過這 6 張圖片的範圍,若是超過範圍,就讓索引值為最大或是最小的那個編號。
slides[i].style.display = "none";
這句寫法用在:把所有的圖片都設為隱藏,而它對應的是 slides[slideIndex - 1].style.display = "block";
這一句寫法,另外,與它相似的另外一個要被清除的東西,則是dots
的active
,使用dots[i].className.replace("active","")
是為了讓dot
小圓點上面,全部有active
的 class 都被清除掉,也就是把 dot 上面的所有 class=”active”
全部都給移除乾淨。不論是slides
的none
,或是dots
的active
,都跟下方的兩句程式碼有所關係。
JavaScript:
slides[slideIndex - 1].style.display = "block";
dots[slideIndex - 1].className += "active";
slides 是針對 slideIndex 索引值
來開啟相對應的slide__item
,而 dots 則是被滑鼠選種的小圓點,會加上active
這個 class名稱,但這東西會累加,所以先前才會需要把所有的active
都給移除乾淨。
最後,我們再 CSS 裡面補上 dot 為 active 時的效果,以及增加 fades 為切換圖片時產生的特效,至於@keyframesm
用法會在後續文章裡補上,這裡先拿來用。程式碼這樣寫。
CSS:
.active,
.dot:hover {
background: rgba(255, 255, 255, 0.9);
cursor: pointer;
}
.fades {
animation: 1.5s fades;
}
@keyframes fades {
from {
opacity: 0.4;
}
to {
opacity: 1;
}
}
顯示結果:
假如你要讓圖片有自動播放的功能,可以在你的 JavaScript 中加入一個setInterval()
來讓圖片可以每隔 3 秒自動的播放。
setInterval(function () {
plusSlides();
}, 3000);
為了確保記憶體內存不會被耗光,在這邊的 HTML 中加入一個refresh
,讓它過每 1 分鐘便會自動刷新頁面一次。 (content裡面數值單位為秒)
<meta http-equiv="refresh" content="60" />
在 CodePen 中則改用history.go(0);
代替refresh
。
setInterval(function () {
history.go(0);
}, 60000);
因為不清楚會不會有什麼 Function 或是什麼其他原因導致記憶體被吃掉,所以我們用一個
refresh
來讓頁面刷新。需要注意的地方則是,在 CodePen 用<meta http-equiv="refresh" content="60" />
會沒有效果,改用history.go(0);
代替,用法可參考Reload on click function not working in javascript。(會有 Page Not Found,故暫不採用history.go(0);
)
雖然 Slideshow 它的原理很簡單,只是靠著索引值來去或是隱藏對應的區塊。但是要我再寫一次一模一樣的東西,我沒有把握能寫的完全一樣,或許過一陣子後,我會找到更好的做法來去取代它,這東西要實作出來,肯定會花一點時間。但是這功能也算挺常見,它可以讓網頁站起來變得更生動,個人認為學起來也是一個挺不錯的選擇!
dots[i].className = dots[i].className.replace("active", "");
跟dots[slideIndex - 1].className += " active";
改成這樣會不會比較好
dots[i].classList.remove("active");
dots[slideIndex - 1].classList.add("active");
不然選擇器.dot標籤一直變長